
#include<pthread.h>
#include<queue>
using namespace std;

const int gmaxcap = 500;
template<class T>
class BlockQueue
{
public:
    BlockQueue(const int &maxcap = gmaxcap) : _maxCap(maxcap)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_pcond, nullptr);
        pthread_cond_init(&_bcond, nullptr);
    }

    void push(const T& t) // 输入型参数
    {
        pthread_mutex_lock(&_mutex);
        while(is_full())
        {
            // 阻塞队列满了，不用你生产了
            pthread_cond_wait(&_pcond,&_mutex);
        }
        _queue.push(t);
        // 提醒消费者消费
        pthread_cond_signal(&_bcond);
        pthread_mutex_unlock(&_mutex);
    }

    void pop(T* t)
    {
        pthread_mutex_lock(&_mutex);
        while(is_empty())
        {
            // 阻塞队列为空，不用消费了
             pthread_cond_wait(&_bcond,&_mutex);
        }
        *t = _queue.front();
        
        _queue.pop();
        // 提醒来生产啦
        pthread_cond_signal(&_bcond);        
        pthread_mutex_unlock(&_mutex);
    }

    ~BlockQueue() 
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_pcond);
        pthread_cond_destroy(&_bcond);
    }

    bool is_empty()
    {
        return _queue.empty();
    }
    bool is_full()
    {
        return _queue.size()==_maxCap;
    }

private:
    std::queue<T> _queue; // 队列
    int _maxCap; // 最大容量
    pthread_mutex_t _mutex; // 互斥锁
    pthread_cond_t _pcond; // 生产者条件变量
    pthread_cond_t _bcond; // 消费者条件变量
};